package com.gdufe.mistakebook.service.impl;

import com.gdufe.mistakebook.constant.StatusConstant;
import com.gdufe.mistakebook.entity.*;
import com.gdufe.mistakebook.entity.dto.QueryQuestionsDto;
import com.gdufe.mistakebook.entity.dto.QuestionDTO;
import com.gdufe.mistakebook.entity.vo.*;
import com.gdufe.mistakebook.entity.vo.count.CreateTimeQuestionCountVO;
import com.gdufe.mistakebook.entity.vo.count.LabelQuestionCountVO;
import com.gdufe.mistakebook.entity.vo.count.PriorityQuestionCountVO;
import com.gdufe.mistakebook.entity.vo.count.SubjectQuestionCountVO;
import com.gdufe.mistakebook.exception.BusinessException;
import com.gdufe.mistakebook.mapper.LabelMapper;
import com.gdufe.mistakebook.mapper.LabelQuestionMapper;
import com.gdufe.mistakebook.mapper.QuestionMapper;
import com.gdufe.mistakebook.result.PageResult;
import com.gdufe.mistakebook.service.QuestionService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author hoshino
 */
@Service
public class QuestionServiceImpl implements QuestionService {

    @Resource
    private QuestionMapper questionMapper;
    @Resource
    private LabelMapper labelMapper;
    @Resource
    private LabelQuestionMapper labelQuestionMapper;

    @Override
    public PageResult pageQuestions(QueryQuestionsDto queryQuestionsDto) {
        //判断参数是否为空
        Integer current = queryQuestionsDto.getCurrent();
        Integer pageSize = queryQuestionsDto.getPageSize();
        String questionTitle = queryQuestionsDto.getQuestionTitle();
        String subjectName = queryQuestionsDto.getSubjectName();
        Date startTime = queryQuestionsDto.getStartTime();
        Date endTime = queryQuestionsDto.getEndTime();
        String labelName = queryQuestionsDto.getLabelName();
        if (current == null || pageSize == null) {
            throw new BusinessException(0, "分页参数不能为空");
        }
        if (current <= 0 || pageSize < 0) {
            throw new BusinessException(0, "分页参数异常");
        }
        //开启分页
        PageHelper.startPage(current, pageSize);
        //条件分页查询
        Page<QueryQuestionsVo2> page = questionMapper.queryQuestions(questionTitle, subjectName, startTime, endTime, labelName);
        List<QueryQuestionsVo2> result = page.getResult();
        List<QueryQuestionsVo> questionsVos = new ArrayList<>();
        //判空
        if (CollectionUtils.isEmpty(result)) {
            return new PageResult(0, questionsVos);
        }
        //将标签字符串转换为列表
        questionsVos = result.stream().map(queryQuestionsVo2 -> {
            QueryQuestionsVo questionsVo = new QueryQuestionsVo();
            BeanUtils.copyProperties(queryQuestionsVo2, questionsVo);
            String labels = queryQuestionsVo2.getLabels();
            if (StringUtils.isNotBlank(labels)) {
                String[] els = labels.split(",");
                List<String> labelList = Arrays.stream(els).collect(Collectors.toList());
                questionsVo.setLabelList(labelList);
            }
            return questionsVo;
        }).collect(Collectors.toList());
        //返回结果
        return new PageResult(page.getTotal(), questionsVos);
    }

    @Override
    public List<QueryQuestionsVo> randomQuestions(Integer count) {
        //随机从数据库中查出count条错题
        List<Question> questionList = questionMapper.randomQueryQuestions(count);
        List<QueryQuestionsVo> questionsVos = new ArrayList<>();
        if (CollectionUtils.isEmpty(questionList)) {
            return questionsVos;
        }
        getQueryQuestionsVoList(questionList, questionsVos);
        //返回数据
        return questionsVos;
    }

    /**
     * 新增错题 及标签
     *
     * @param questionDTO
     */
    @Override
    @Transactional
    public void insertQuestionWithLabel(QuestionDTO questionDTO) {
        Question question = new Question();
        BeanUtils.copyProperties(questionDTO, question);

        questionDTO.setUserId(1);

        // 设置错题所属用户
        question.setUserId(questionDTO.getUserId());
        // 设置错题状态 默认存在
        question.setStatus(StatusConstant.STATUS_EXISTS);
        // 创建错题时间
        question.setCreateTime(new Date());
        // 更改错题时间
        question.setUpdateTime(new Date());
        // 插入错题
        questionMapper.insertQuestion(question);

        // 获取标签列表
        List<String> labelList = questionDTO.getLabelList();
        if (labelList != null) {
            insertLabel(questionDTO, labelList, question);
        }
    }

    /**
     * 修改错题信息 以及标签表信息
     *
     * @param questionDTO
     */
    @Override
    @Transactional
    public void updateQuestionWithLabel(QuestionDTO questionDTO) {
        // 修改错题信息
        Question question = new Question();
        questionDTO.setUserId(1);
        BeanUtils.copyProperties(questionDTO, question);
        // 修改错题时间
        question.setUpdateTime(new Date());
        questionMapper.update(question);
        // 更改错题后 对标签信息 及关系进行更改
        // 获取标签列表
        List<String> labelList = questionDTO.getLabelList();
        if (labelList != null) {
            // 先删除所有的标签问题关系
            labelQuestionMapper.delete(question.getId());
            // 再增加新的标签问题关系
            insertLabel(questionDTO, labelList, question);
        }
    }

    // 插入标签 及错题与标签关系
    private void insertLabel(QuestionDTO questionDTO, List<String> labelList, Question question) {
        for (String labelName : labelList) {
            // 首先查询错题对应的标签是否存在
            Label labelDb = labelMapper.getLabelByName(labelName, questionDTO.getUserId());
            Label label = new Label();
            if (labelDb == null) {
                // 若标签不存在 则将新的标签保存到标签表中
                label.setLabelName(labelName);
                label.setUserId(questionDTO.getUserId());
                label.setStatus(StatusConstant.STATUS_EXISTS);
                label.setCreateTime(new Date());
                label.setUpdateTime(new Date());
                labelMapper.insertLabel(label);
            } else if (labelDb.getStatus().equals(StatusConstant.STATUS_DELETE)) {
                // 若标签存在 但处于删除禁用状态 更新其状态
                Label newLabel = Label.builder()
                        .id(labelDb.getId())
                        .status(StatusConstant.STATUS_EXISTS)
                        .updateTime(new Date())
                        .build();
                label.setId(labelDb.getId());
                labelMapper.update(newLabel);
            } else {
                // 标签已存在 且处于使用状态
                // 给标签标记id
                label.setId(labelDb.getId());
            }
            // 然后根据标签id 与 错题id 建立关系并保存到关系表中
            LabelQuestion labelQuestion = LabelQuestion.builder()
                    .questionId(question.getId())
                    .labelId(label.getId())
                    .status(StatusConstant.STATUS_EXISTS)
                    .build();
            // 保存标签与问题的关系
            labelQuestionMapper.insert(labelQuestion);
        }
    }

    /**
     * 删除错题及 标签关系
     *
     * @param status
     * @param questionId
     */
    @Override
    @Transactional
    public void deleteQuestionWithLabel(Integer status, Integer questionId) {
        Question question = Question.builder()
                .status(status)
                .id(questionId)
                .build();
        // 逻辑删除问题
        questionMapper.update(question);
        // 删除问题所对应的标签关系
        labelQuestionMapper.delete(questionId);
    }


    /**
     * 查询错题列表
     *
     * @param questionList
     * @param questionsVos
     * @return
     */
    private void getQueryQuestionsVoList(List<Question> questionList, List<QueryQuestionsVo> questionsVos) {
        //根据错题查出对应标签
        for (Question question : questionList) {
            //根据错题ID查询对应标签ID
            List<Integer> labelIds = labelQuestionMapper.getLabelIdsByQuestionId(question.getId());
            //根据标签ID批量查询标签名称
            List<String> labelNameList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(labelIds)) {
                labelNameList = labelMapper.getLabelNamesByIds(labelIds);
            }
            QueryQuestionsVo questionsVo = new QueryQuestionsVo();
            BeanUtils.copyProperties(question, questionsVo);
            questionsVo.setLabelList(labelNameList);
            questionsVos.add(questionsVo);
        }
    }

    /**
     * 根据id获取错题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO getDetails(Integer id) {
        QuestionVO questionVO = new QuestionVO();
        // 首先根据错题id 获取错题信息
        Question question = questionMapper.selectById(id);
        // 将错题信息记录
        BeanUtils.copyProperties(question, questionVO);
        // 再根据错题id 查询错题与标签的关系
        List<Integer> labelIds = labelQuestionMapper.getLabelIdsByQuestionId(id);
        // 根据标签id获取标签列表
        List<Label> labelList = new ArrayList<>();
        for (Integer labelId : labelIds) {
            Label label = labelMapper.getLabelById(labelId);
            labelList.add(label);
        }
        questionVO.setLabelList(labelList); // 记录标签列表
        return questionVO;
    }

    @Override
    public List<SubjectQuestionCountVO> getSubjectAmount() {
        return questionMapper.selectSubjectQuestionCount();
    }

    @Override
    public List<LabelQuestionCountVO> getLabelAmount() {
        return labelQuestionMapper.selectLabelQuestionCount();
    }

    @Override
    public List<PriorityQuestionCountVO> getPriorityAmount() {
        return questionMapper.selectPriorityQuestionCount();
    }

    @Override
    public List<CreateTimeQuestionCountVO> getCeateTimeAmount() {
        return questionMapper.selectCreateTimeQuestionCount();
    }

}
